home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-08-04 | 9.3 KB | 380 lines | [TEXT/CWIE] |
- //
- // PullStream.CPP
- //
- // >>> ⌐ 1996-1997 Microsoft Corporation. All rights reserved. <<<
- //
- // Implements pull-data type stream access
- //
-
- #include "AXContainerHeaders.h"
-
- extern FORMATETC g_NullFormatEtc;
-
-
- //
- // CPullStreamNotify::~CPullStreamNotify
- //
-
- CPullStreamNotify::~CPullStreamNotify()
- {
- if (m_pStream != NULL)
- CoTaskMemFree(m_pStream);
- }
-
- //
- // CPullStreamNotify::OnWrite
- //
-
- int32
- CPullStreamNotify::OnWrite(NPStream *stream, int32 offset, int32 len, void
- *buffer)
- {
- #pragma unused (stream, offset)
- int32 BytesWritten;
-
- if (m_pStream == NULL)
- m_pStream = (LPVOID) CoTaskMemAlloc(STREAM_BUFFER_SIZE);
-
- if ((m_StreamLength + len) <= STREAM_BUFFER_SIZE)
- {
- BlockMove(buffer, ((LPBYTE) m_pStream + m_StreamLength), len);
- m_StreamLength += len;
- BytesWritten = len;
- }
- else
- {
- // Returning a negative value causes the stream to error out and be
- // destroyed.
- BytesWritten = -1;
- }
-
- m_ReadyToRead -= len;
-
- return BytesWritten;
- }
-
- int32
- CPullStreamNotify::OnWriteReady(NPStream *stream)
- {
- #pragma unused (stream)
- return m_ReadyToRead;
- }
-
- //
- // CPullOleStreamNotify::IUnknown::QueryInterface
- //
-
- STDMETHODIMP
- CPullOleStreamNotify::QueryInterface(REFIID riid, LPVOID *ppvObj)
- {
- HRESULT hr;
- LPVOID pv;
-
- if (riid == IID_IUnknown || riid == IID_IStream) {
- pv = (LPVOID)(LPSTREAM) this;
- ++m_cRef;
- hr = ResultFromScode(S_OK);
- } else {
- pv = NULL;
- hr = ResultFromScode(E_NOINTERFACE);
- }
-
- *ppvObj = pv;
- return hr;
- }
-
- //
- // CPullOleStreamNotify::IUnknown::AddRef
- //
-
- STDMETHODIMP_(ULONG)
- CPullOleStreamNotify::AddRef(void)
- {
- return ++m_cRef;
- }
-
- //
- // CPullOleStreamNotify::IUnknown::Release
- //
-
- STDMETHODIMP_(ULONG)
- CPullOleStreamNotify::Release(void)
- {
- if (--m_cRef != 0)
- return m_cRef;
-
- delete this;
- return 0;
- }
-
- //
- // CPullOleStreamNotify::IStream::Read
- //
-
- STDMETHODIMP
- CPullOleStreamNotify::Read(void *pv, DWORD cb, LPDWORD pcbRead)
- {
- // Verify that we're not try to read more bytes than are available. If we
- // are, clip the actual number of bytes copied. The OLE32 memory stream
- // implementation doesn't return an error, so we won't either.
- if (((LONG) cb < 0) || (cb + (ULONG) m_SeekPosition > (ULONG) m_StreamLength))
- {
- if (m_fAsyncStreamInProgress)
- {
- // Special case: if we're in the middle of streaming some data from
- // the network, return E_PENDING so that async binding works
- // correctly.
- // BUGBUG: Above if statement probably isn't adequate, review this.
- return ResultFromScode(E_PENDING);
- }
- else
- {
- cb = m_StreamLength - m_SeekPosition;
- }
- }
-
- if (cb > 0)
- {
- BlockMove((LPBYTE) m_pStream + m_SeekPosition, pv, cb);
- m_SeekPosition += cb;
- }
-
- if (pcbRead != NULL)
- *pcbRead = cb;
-
- // if all data has been read, pull another buffer full
- if(m_ReadyToRead == 0 && m_SeekPosition >= STREAM_BUFFER_SIZE)
- {
- m_SeekPosition = 0;
- m_StreamLength = 0;
- m_ReadyToRead = STREAM_BUFFER_SIZE;
- }
-
- return ResultFromScode(S_OK);
- }
-
- //
- // CPullOleStreamNotify::IStream::Write
- //
-
- STDMETHODIMP
- CPullOleStreamNotify::Write(void const *pv, DWORD cb, LPDWORD pcbWritten)
- {
- #pragma unused (pv, cb, pcbWritten)
- return ResultFromScode(STG_E_ACCESSDENIED);
- }
-
- //
- // CPullOleStreamNotify::IStream::Seek
- //
-
- STDMETHODIMP
- CPullOleStreamNotify::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin,
- ULARGE_INTEGER *plibNewPosition)
- {
- #pragma unused (dlibMove, dwOrigin, plibNewPosition)
- return ResultFromScode(STG_E_INVALIDFUNCTION);
- }
-
- //
- // CPullOleStreamNotify::IStream::SetSize
- //
-
- STDMETHODIMP
- CPullOleStreamNotify::SetSize(ULARGE_INTEGER libNewSize)
- {
- #pragma unused (libNewSize)
- // We're a read-only stream, so there's no reason to resize our stream.
- return ResultFromScode(STG_E_INVALIDFUNCTION);
- }
-
- //
- // CPullOleStreamNotify::IStream::CopyTo
- //
-
- STDMETHODIMP
- CPullOleStreamNotify::CopyTo(LPSTREAM pstm, ULARGE_INTEGER cb, ULARGE_INTEGER
- *pcbRead, ULARGE_INTEGER *pcbWritten)
- {
- #pragma unused (pstm, cb, pcbRead, pcbWritten)
- // There's no good reason for this not to be implemented.
- return ResultFromScode(E_NOTIMPL);
- }
-
- //
- // CPullOleStreamNotify::IStream::Commit
- //
-
- STDMETHODIMP
- CPullOleStreamNotify::Commit(DWORD grfCommitFlags)
- {
- #pragma unused (grfCommitFlags)
- // We can always "commit" because it's not possible to write to the stream.
- return ResultFromScode(S_OK);
- }
-
- //
- // CPullOleStreamNotify::IStream::Revert
- //
-
- STDMETHODIMP
- CPullOleStreamNotify::Revert(void)
- {
- // We can always "revert" because it's not possible to write to the stream.
- return ResultFromScode(S_OK);
- }
-
- //
- // CPullOleStreamNotify::IStream::LockRegion
- //
-
- STDMETHODIMP
- CPullOleStreamNotify::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
- DWORD dwLockType)
- {
- #pragma unused (libOffset, cb, dwLockType)
- return ResultFromScode(STG_E_INVALIDFUNCTION);
- }
-
- //
- // CPullOleStreamNotify::IStream::UnlockRegion
- //
-
- STDMETHODIMP
- CPullOleStreamNotify::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER
- cb, DWORD dwLockType)
- {
- #pragma unused (libOffset, cb, dwLockType)
- return ResultFromScode(STG_E_INVALIDFUNCTION);
- }
-
- //
- // CPullOleStreamNotify::IStream::Stat
- //
-
- STDMETHODIMP
- CPullOleStreamNotify::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
- {
- #pragma unused (grfStatFlag)
- // Implementation lifted from OLE32's memory stream.
- memset(pstatstg, 0, sizeof(*pstatstg));
- pstatstg->type = STGTY_STREAM;
- pstatstg->cbSize.LowPart = m_StreamLength;
- return ResultFromScode(S_OK);
- }
-
- //
- // CPullOleStreamNotify::IStream::Clone
- //
-
- STDMETHODIMP
- CPullOleStreamNotify::Clone(LPSTREAM *ppstm)
- {
- *ppstm = NULL;
- return ResultFromScode(E_NOTIMPL);
- }
-
- //
- // CBindingMemoryStreamNotify::OnWrite
- //
- // Extends the default memory stream implementation by notifying the client of
- // data availability.
- //
-
- int32
- CBindingPullStreamNotify::OnWrite(NPStream *stream, int32 offset, int32 len,
- void *buffer)
- {
- int32 BytesWritten;
- ULONG BindStatus;
- DWORD fBSCF;
-
- // Tag the stream such that requests for unavailable data made against our
- // IStream return E_PENDING.
- m_fAsyncStreamInProgress = TRUE;
-
- BytesWritten = CPullOleStreamNotify::OnWrite(stream, offset, len, buffer);
-
- if (BytesWritten > 0) {
-
- if (!m_fDeliveredFirstNotify) {
- m_fDeliveredFirstNotify = TRUE;
- BindStatus = BINDSTATUS_BEGINDOWNLOADDATA;
- fBSCF = BSCF_FIRSTDATANOTIFICATION;
- } else {
- BindStatus = BINDSTATUS_DOWNLOADINGDATA;
- fBSCF = BSCF_INTERMEDIATEDATANOTIFICATION;
- }
-
- m_pBinding->m_pbsc->OnProgress((ULONG) m_StreamLength,
- (ULONG) m_StreamLength, BindStatus, m_pszURL);
-
- mStorageMedium.tymed = TYMED_ISTREAM;
- mStorageMedium.u.pstm = (LPSTREAM) this;
- mStorageMedium.pUnkForRelease = (LPUNKNOWN) this;
- m_pBinding->m_pbsc->OnDataAvailable(fBSCF, BytesWritten,
- &g_NullFormatEtc, &mStorageMedium);
-
- // If the client called IBinding::Abort, return an error so as to
- // force the stream to terminate.
- if (m_pBinding->m_fAborted)
- BytesWritten = -1;
- }
-
- // If BytesWritten is negative, then the stream will be terminated. The
- // client will be notified of the error in the OnDestroyStream method.
- return BytesWritten;
- }
-
- //
- // CBindingMemoryStreamNotify::OnDestroyStream
- //
- // Extends the default memory stream implementation by notifying the client
- // that the binding operation is complete.
- //
-
- NPError
- CBindingPullStreamNotify::OnDestroyStream(NPStream *stream, NPError reason)
- {
- #pragma unused (stream)
- HRESULT hr;
-
- m_fAsyncStreamInProgress = FALSE;
-
- // You would think Netscape would pass the right reason code to us, but it
- // always returns a zero on success, so maybe they want NPERR_NO_ERROR???
- if ((reason == NPERR_NO_ERROR || reason == NPRES_DONE) &&
- !m_pBinding->m_fAborted) {
- // Send the final progress notification.
- m_pBinding->m_pbsc->OnProgress((ULONG) m_StreamLength,
- (ULONG) m_StreamLength, BINDSTATUS_ENDDOWNLOADDATA, m_pszURL);
-
- // Although the data stream hasn't changed, we need to send the last
- // data notification.
- mStorageMedium.tymed = TYMED_ISTREAM;
- mStorageMedium.u.pstm = (LPSTREAM) this;
- mStorageMedium.pUnkForRelease = (LPUNKNOWN) this;
- m_pBinding->m_pbsc->OnDataAvailable(BSCF_LASTDATANOTIFICATION,
- m_StreamLength, &g_NullFormatEtc, &mStorageMedium);
-
- hr = ResultFromScode(S_OK);
- } else {
- hr = ResultFromScode(E_ABORT);
- }
-
- // Notify the callback that the binding has stopped. Plus, we're through
- // with the binding object, so we're ready to throw it away. The client
- // is supposed to release the pointer in the OnStopBinding method, so we'll
- // make sure we don't leak anything by just deleting the binding.
- m_pBinding->m_pbsc->OnStopBinding(hr, NULL);
- delete m_pBinding;
- m_pBinding = NULL;
-
- // We're through with this binding callback object. The user may be
- // holding on to our stream object though, so we must pay attention to our
- // reference count.
- this->Release();
-
- return NPERR_NO_ERROR;
- }
-